package deltax.common.resource
{
    import deltax.common.*;
    import deltax.common.StartUpParams.*;
    import deltax.common.log.*;
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.system.*;
    import flash.utils.*;

    public class FileRevisionManager extends EventDispatcher
    {
        private var m_projectVersion:Version;
        private var m_mainFileBuildDate:String;
        private var m_svnTotalRevisions:Dictionary;
        private var m_remoteRevisionMap:Dictionary;
        private var m_fileLoadStatus:Dictionary;
        private var m_fileSymbolClassNames:Dictionary;
        public static const REVISION_FILE_BIN:uint = 0;
        public static const REVISION_FILE_CONFIG:uint = 1;
        public static const REVISION_FILE_DATA:uint = 2;
        public static const REVISION_FILE_COUNT:uint = 3;
        public static const EVENT_VERSION_FILE_LOADED:String = "VersionFilesLoaded";
        public static const EVENT_REVISION_FILE_LOADED:String = "RevisionFilesLoaded";
        public static const EVENT_ALL_REVISION_FILES_LOADED:String = "AllRevisionFilesLoaded";
        private static var m_instance:FileRevisionManager;

        public function FileRevisionManager(param1:SingletonEnforcer)
        {
            this.m_projectVersion = new Version();
            this.m_svnTotalRevisions = new Dictionary();
            this.m_remoteRevisionMap = new Dictionary();
            this.m_fileLoadStatus = new Dictionary();
            this.m_fileSymbolClassNames = new Dictionary();
            return;
        }// end function

        public function get projectVersion() : Version
        {
            return this.m_projectVersion;
        }// end function

        public function loadProjectVersionFile(param1:String) : void
        {
            var versionFileUrl:String;
            var myLoader:URLLoader;
            var projVersionLoaded:Function;
            var splitted:Array;
            var ext:String;
            var url:* = param1;
            projVersionLoaded = function (event:Event) : void
            {
                var _loc_5:String = null;
                var _loc_6:String = null;
                var _loc_2:* = new StringDataParser(String(myLoader.data));
                var _loc_3:* = _loc_2.getNextToken();
                m_projectVersion.fromString(_loc_3);
                DictionaryUtil.clearDictionary(m_svnTotalRevisions);
                var _loc_4:* = REVISION_FILE_BIN;
                while (!_loc_2.reachedEOF)
                {
                    
                    _loc_5 = _loc_2.getNextToken();
                    m_svnTotalRevisions[_loc_5] = [_loc_2.getNextInt(), _loc_4];
                    _loc_6 = _loc_5.split(".").shift() + "_txt";
                    m_fileSymbolClassNames[_loc_4] = _loc_6;
                    _loc_4 = _loc_4 + 1;
                }
                if (hasEventListener(EVENT_VERSION_FILE_LOADED))
                {
                    dispatchEvent(new DataEvent(EVENT_VERSION_FILE_LOADED, false, false));
                }
                return;
            }// end function
            ;
            var versionParamFromOutside:* = StartUpParams.m_params["version"];
            var developVersion:* = StartUpParams.developVersion;
            if (developVersion || !versionParamFromOutside)
            {
                versionFileUrl = url + randomUrlPostFix;
            }
            else
            {
                splitted = url.split(".");
                ext = splitted.pop();
                versionFileUrl = splitted.join(".") + "_" + versionParamFromOutside + "." + ext;
            }
            myLoader = new URLLoader(new URLRequest(versionFileUrl));
            myLoader.dataFormat = URLLoaderDataFormat.TEXT;
            myLoader.addEventListener(Event.COMPLETE, projVersionLoaded);
            return;
        }// end function

        public function getRevisionFileNameByType(param1:uint) : String
        {
            var _loc_3:String = null;
            var _loc_4:Array = null;
            var _loc_5:uint = 0;
            var _loc_6:uint = 0;
            var _loc_7:int = 0;
            var _loc_2:* = StartUpParams.developVersion;
            for (_loc_3 in this.m_svnTotalRevisions)
            {
                
                _loc_4 = this.m_svnTotalRevisions[_loc_3];
                _loc_5 = _loc_4[0];
                _loc_6 = _loc_4[1];
                if (_loc_6 == param1)
                {
                    if (_loc_2)
                    {
                        return _loc_3 + "?v=" + _loc_5;
                    }
                    _loc_7 = _loc_3.lastIndexOf(".");
                    if (_loc_7 >= 0)
                    {
                        return _loc_3.substr(0, _loc_7) + "_" + _loc_5 + _loc_3.substr(_loc_7);
                    }
                    return _loc_3 + "_" + _loc_5;
                }
            }
            return "";
        }// end function

        public function getRevisionByPathType(param1:uint) : uint
        {
            var _loc_2:String = null;
            var _loc_3:Array = null;
            var _loc_4:uint = 0;
            var _loc_5:uint = 0;
            for (_loc_2 in this.m_svnTotalRevisions)
            {
                
                _loc_3 = this.m_svnTotalRevisions[_loc_2];
                _loc_4 = _loc_3[0];
                _loc_5 = _loc_3[1];
                if (_loc_5 == param1)
                {
                    return _loc_4;
                }
            }
            return 0;
        }// end function

        public function loadRevisionMapFile(param1:uint, param2:String) : void
        {
            var projVersionLoaded:Function;
            var _generalIOErrorHandler:Function;
            var loader:Loader;
            var loaderContext:LoaderContext;
            var urlLoader:URLLoader;
            var revisionFileType:* = param1;
            var rootUrlPath:* = param2;
            projVersionLoaded = function (event:Event) : void
            {
                var cls:Class;
                var loaderInfo:LoaderInfo;
                var className:String;
                var curTime:int;
                var data:ByteArray;
                var event:* = event;
                if (event.target is URLLoader)
                {
                    parseRevisionFile(m_remoteRevisionMap, String(urlLoader.data));
                    urlLoader.removeEventListener(Event.COMPLETE, projVersionLoaded);
                    urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, _generalIOErrorHandler);
                }
                else
                {
                    try
                    {
                        className = m_fileSymbolClassNames[revisionFileType];
                        cls = loaderContext.applicationDomain.getDefinition(className) as Class;
                    }
                    catch (e:ReferenceError)
                    {
                        cls;
                        dtrace(LogLevel.FATAL, e.message);
                    }
                    if (cls)
                    {
                        curTime = getTimer();
                        data = new cls;
                        parseRevisionFileFromBytes(m_remoteRevisionMap, data);
                        dtrace(LogLevel.DEBUG_ONLY, "parse data rev file cost: ", getTimer() - curTime);
                    }
                    loaderInfo = LoaderInfo(event.target);
                    loaderInfo.removeEventListener(Event.COMPLETE, projVersionLoaded);
                    loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, _generalIOErrorHandler);
                }
                onRevisionFileLoadedOrFailed(revisionFileType);
                return;
            }// end function
            ;
            _generalIOErrorHandler = function (event:IOErrorEvent) : void
            {
                var _loc_2:LoaderInfo = null;
                if (event.target is URLLoader)
                {
                    urlLoader.removeEventListener(Event.COMPLETE, projVersionLoaded);
                    urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, _generalIOErrorHandler);
                }
                else
                {
                    _loc_2 = LoaderInfo(event.target);
                    _loc_2.removeEventListener(Event.COMPLETE, projVersionLoaded);
                    _loc_2.removeEventListener(IOErrorEvent.IO_ERROR, _generalIOErrorHandler);
                }
                dtrace(LogLevel.FATAL, event.text);
                onRevisionFileLoadedOrFailed(revisionFileType);
                return;
            }// end function
            ;
            var url:* = this.getRevisionFileNameByType(revisionFileType);
            if (!url)
            {
                this.onRevisionFileLoadedOrFailed(revisionFileType);
                return;
            }
            url = rootUrlPath + url;
            this.m_fileLoadStatus[revisionFileType] = true;
            if (url.lastIndexOf(".swf") >= 0)
            {
                loader = new Loader();
                loaderContext = new LoaderContext();
                loaderContext.applicationDomain = new ApplicationDomain();
                loader.load(new URLRequest(url), loaderContext);
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, projVersionLoaded);
                loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _generalIOErrorHandler);
            }
            else
            {
                urlLoader = new URLLoader(new URLRequest(url));
                urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
                urlLoader.addEventListener(Event.COMPLETE, projVersionLoaded);
                urlLoader.addEventListener(IOErrorEvent.IO_ERROR, _generalIOErrorHandler);
            }
            return;
        }// end function

        private function onRevisionFileLoadedOrFailed(param1:uint) : void
        {
            if (hasEventListener(EVENT_REVISION_FILE_LOADED))
            {
                dispatchEvent(new DataEvent(EVENT_REVISION_FILE_LOADED, false, false, param1.toString()));
            }
            delete this.m_fileLoadStatus[param1];
            this.checkLoadStatus();
            return;
        }// end function

        private function parseRevisionFileFromBytes(param1:Dictionary, param2:ByteArray) : void
        {
            var _loc_5:String = null;
            var _loc_6:String = null;
            var _loc_7:uint = 0;
            param2.endian = Endian.LITTLE_ENDIAN;
            var _loc_3:* = param2.position;
            var _loc_4:* = param2.length;
            while (_loc_3 < _loc_4)
            {
                
                if (param2[_loc_3] == 10)
                {
                    break;
                }
                _loc_7 = _loc_3;
                while (_loc_3 < _loc_4 && param2[_loc_3] != 32)
                {
                    
                    _loc_3 = _loc_3 + 1;
                }
                param2.position = _loc_7;
                _loc_5 = param2.readUTFBytes(_loc_3 - _loc_7);
                while (_loc_3 < _loc_4 && param2[_loc_3] == 32)
                {
                    
                    _loc_3 = _loc_3 + 1;
                }
                _loc_7 = _loc_3;
                while (_loc_3 < _loc_4 && param2[_loc_3] != 10)
                {
                    
                    _loc_3 = _loc_3 + 1;
                }
                param2.position = _loc_7;
                _loc_6 = param2.readUTFBytes(_loc_3 - _loc_7);
                param1[_loc_6.toLowerCase()] = parseInt(_loc_5);
                _loc_3 = _loc_3 + 1;
            }
            return;
        }// end function

        private function parseRevisionFile(param1:Dictionary, param2:String) : void
        {
            var _loc_4:uint = 0;
            var _loc_5:String = null;
            var _loc_3:StringDataParser = new StringDataParser(param2);
            _loc_3.skipWhiteSpace();
            while (!_loc_3.reachedEOF)
            {
                
                _loc_4 = _loc_3.getNextInt();
                _loc_5 = _loc_3.getLine();
                param1[_loc_5.toLowerCase()] = _loc_4;
            }
            return;
        }// end function

        private function checkLoadStatus() : void
        {
            if (DictionaryUtil.isDictionaryEmpty(this.m_fileLoadStatus))
            {
                dispatchEvent(new DataEvent(EVENT_ALL_REVISION_FILES_LOADED));
            }
            return;
        }// end function

        public function getFileVersion(param1:String) : uint
        {
            var _loc_2:* = Enviroment.convertURLForQueryPackage(param1);
            return this.m_remoteRevisionMap[_loc_2];
        }// end function

        public function getVersionedURL(param1:String) : String
        {
            var _loc_4:Array = null;
            var _loc_5:String = null;
            var _loc_2:* = Enviroment.convertURLForQueryPackage(param1);
            var _loc_3:* = this.m_remoteRevisionMap[_loc_2];
            if (_loc_3)
            {
                if (StartUpParams.developVersion)
                {
                    return param1 + "?v=" + _loc_3;
                }
                _loc_4 = param1.split(".");
                _loc_5 = _loc_4.pop();
                return _loc_4.join(".") + "_" + _loc_3 + "." + _loc_5;
            }
            else
            {
                return param1;
            }
        }// end function

        public static function get instance() : FileRevisionManager
        {
            var _loc_1:* = m_instance || new FileRevisionManager(new SingletonEnforcer());
            m_instance = m_instance || new FileRevisionManager(new SingletonEnforcer());
            return _loc_1;
        }// end function

        public static function get randomUrlPostFix() : String
        {
            return "?r=" + new Date().time;
        }// end function

    }
}

class SingletonEnforcer extends Object
{

    function SingletonEnforcer()
    {
        return;
    }// end function

}

